/*
 * -------------------------------------- 
 * FileName: seq_list.c 
 * Content:
 *      顺序表
 * Auther:  杨则瑞 
 * Encode:  utf-8 | CRLF                  
 * -------------------------------------- 
 */

#include<seq_list.h>

#define ns(title) sqList_##title

#define try_error(errors) \
do { \
    if(self->_error_handler != NULL)\
    { \
        *self->_error_handler = errors; \
    } \
} while (0)


// 默认顺序表长度
const int sqList_default_length = 80;
// 默认顺序表增长量
const int sqList_dft_incri = 80;


//初始化顺序表
void sqList_init( sqList_t * self, size_t elemSize, sqList_error_t * error_handler)
{
    self->_error_handler = error_handler;
    self->_elemSize = elemSize;
    self->_len = 0;
    self->_capacity = sqList_default_length;

    self->data = malloc(self->_elemSize * self->_capacity);

    if(self->data == NULL) 
    {
        self->_capacity = 0;

        try_error(sqList_INSUFFICIENT_MEMORORY);

        _debug("Insufficient Memory","Error");

        return;
    }

    return;
}

//析构顺序表
void sqList_uninit( sqList_t * self)
{
    self->_elemSize = 0;
    self->_len = 0;
    self->_capacity = 0;

    free(self->data);

    return;
}

// 获取位于index偏移量的元素地址
void * sqList_get(sqList_t * self, size_t index)
{
    if(index >= self->_len)
    {
        try_error(sqList_INDEX_OUT_OF_BOUND);

        _debug("Index Too much","Error");
        
        return NULL;
    }

    return self->data + index * (self->_elemSize);
}

// 拓容与缩容
void sqList_reserve(sqList_t * self, size_t new_len)
{

    if(new_len <= sqList_default_length)
    {
        return;
    }

    void * tmp = realloc(self->data,new_len * self->_elemSize);

    if(tmp == NULL) 
    {

        try_error(sqList_INSUFFICIENT_MEMORORY);

        _debug("Insufficient Memory","Error");

        return;
    }

    self->data = tmp;
    self->_capacity = new_len;
}

// 在指定位置插入空元素，并返回
void * sqList_insertive_get(sqList_t * self, size_t index)
{
    if(index > self->_len)
    {
        try_error(sqList_INDEX_OUT_OF_BOUND);

        _debug("Index Too much","Error");
        
        return NULL;
    }
    
    if(self->_len + 1 > self->_capacity) 
    {
        size_t tmp = self->_capacity;
        sqList_reserve(self, self->_capacity + sqList_dft_incri);
        if(self->_capacity == tmp)
        {
            
            try_error(sqList_INSUFFICIENT_MEMORORY);

            _debug("Insufficient Memory","Error");

            return NULL;
        }
    }

    // 移动所有位于后方的元素
    for(size_t i = self->_len + 1; i + 1 > index; --i)
    {
        memcpy(
            self->data + (i) * self->_elemSize,
            self->data + (i-1) * self->_elemSize,
            self->_elemSize
        );
    }

    self->_len += 1;

    // 返回空出来的位
    return self->data + index * self->_elemSize;
}

void sqList_erase(sqList_t * self, size_t index)
{
    // 超出下标访问处理，包括从空表中删除
    if(index >= self->_len)
    {
        try_error(sqList_INDEX_OUT_OF_BOUND);

        _debug("Index Too much","Error");
        
        return;
    }
    
   
    //移动所有后方元素
    for(size_t i = index; i < self->_len; ++i)
    {
        memcpy(
            self->data + (i) * self->_elemSize,
            self->data + (i+1) * self->_elemSize,
            self->_elemSize
        );
    }

    // 判断是否达到需要缩容的情况
    if((self->_len - 1)/sqList_dft_incri != (self->_len - 1)/sqList_dft_incri) 
    {
        size_t tmp = self->_capacity;
        sqList_reserve(self, self->_capacity - sqList_dft_incri);
        if(self->_capacity == tmp)
        {
            
            try_error(sqList_INSUFFICIENT_MEMORORY);

            _debug("Insufficient Memory","Error");
            
            return;
        }
    }

    self->_len -= 1;

    return;
}

#undef try_error
#undef ns 
